#include "visitordata.h"
#include <algorithm>
#include <assert.h>

void SemanticVisitorData::addLibraryClass(const std::string & s, ClassSemantic * c)
{
	m_libraryclasses.insert(std::make_pair<std::string,ClassSemantic*>(s,c));
}

void SemanticVisitorData::createLibraryClasses()
{
	ClassSemantic * any=new ClassSemantic();
	any->m_class=new ClassNode(YYLTYPE(),new std::string("ANY"));
	any->m_class->setType(CLM_DEFERRED);
	any->m_is_interface=false;
	any->toggleVisited();
	addLibraryClass("ANY",any);

	

	createInteger();
	createReal();
	createBoolean();
	createCharacter();
	createString();
	createStreams();
}


void SemanticVisitorData::createInteger()
{
    ClassSemantic * integer=new ClassSemantic();
	integer->toggleVisited();
	integer->m_is_interface=false;
	integer->addInheritance("ANY",InheritanceSemantic());
	integer->m_class=new ClassNode(YYLTYPE(),new std::string("INTEGER"));
	
	Method clone;
	clone.m_classname="INTEGER";
	clone.m_clients.push_back("ANY");
	clone.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"));
	clone.m_routine=NULL;
	clone.m_type=FDT_LIBRARY;
	clone.m_realname="CLONE";
	integer->addMethod("CLONE",clone);

	//Arithmetic
	{
	
	std::string possible_args[2]={"INTEGER","REAL"};
	std::string arith_operators[5]={"+","-","*","/","^"};
	std::string arith_mnemonic[5]={"SUM","SUB","MUL","DIV","POW"};
	for (int i=0;i<5;i++)
	{
		for (int j=0;j<2;j++)
		{
			Method m;
			m.m_classname="INTEGER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;
			
			std::string methodname=arith_mnemonic[i]+possible_args[j];
			m.m_realname=methodname;
			integer->addMethod(methodname,m);
			integer->addOperator(Operator(m.m_clients,m.m_classname,methodname,arith_operators[i]));
		}
	}
    
    }

	//Additional arithmetic
	{
			Method m;
			m.m_classname="INTEGER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname="TWOSLASHES";
			m.m_realname=methodname;
			integer->addMethod(methodname,m);
			integer->addOperator(Operator(m.m_clients,m.m_classname,methodname,"\\\\"));
	}
	{
			Method m;
			m.m_classname="INTEGER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname="TWOBACKSLASHES";
			m.m_realname=methodname;
			integer->addMethod(methodname,m);
			integer->addOperator(Operator(m.m_clients,m.m_classname,methodname,"//"));
	}


	//Compare operators
	{
	 std::string possible_args[2]={"INTEGER","REAL"};
	 std::string arith_operators[8]={"<",">","<=",">=","~","/~","=","/="};
	 std::string arith_mnemonic[8]={"LS","GT","LEQ","GEQ","SEQ","NSEQ","EQ","NEQ"};

	 for (int i=0;i<8;i++)
	 {
		for (int j=0;j<2;j++)
		{
			Method m;
			m.m_classname="INTEGER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("BOOLEAN"));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=arith_mnemonic[i]+possible_args[j];
			m.m_realname=methodname;
			integer->addMethod(methodname,m);
			integer->addOperator(Operator(m.m_clients,m.m_classname,methodname,arith_operators[i]));
		}
	 }
	
	}

	std::string possible_types[3]={"REAL","CHARACTER","STRING"};
	//Converts to
	{
	 std::string to="TO_";
     for (int i=0;i<3;i++)
	 {
			Method m;
			m.m_classname="INTEGER";
			m.m_clients.push_back("ANY");
			//m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string(possible_types[i]));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=to+possible_types[i];
			m.m_realname=methodname;
			integer->addMethod(methodname,m);
			integer->addConvertTo(possible_types[i],methodname);
	 }
	}
	//Converts from
	{
	 std::string from="FROM_";
     for (int i=0;i<3;i++)
	 {
			Method m;
			m.m_classname="INTEGER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_types[i]))));
			m.m_return_type=NULL;
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=from+possible_types[i];
			m.m_realname=methodname;
			integer->addMethod(methodname,m);
			integer->addConvertFrom(possible_types[i],methodname);
	 }
	}

	addLibraryClass("INTEGER",integer);
}


void SemanticVisitorData::createReal()
{
    ClassSemantic * real=new ClassSemantic();
	real->toggleVisited();
	real->m_is_interface=false;
	real->addInheritance("ANY",InheritanceSemantic());
	real->m_class=new ClassNode(YYLTYPE(),new std::string("REAL"));
	
	
	Method clone;
	clone.m_classname="REAL";
	clone.m_clients.push_back("ANY");
	clone.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("REAL"));
	clone.m_routine=NULL;
	clone.m_type=FDT_LIBRARY;
	clone.m_realname="CLONE";
	real->addMethod("CLONE",clone);
	//Arithmetic
	{
	
	std::string possible_args[2]={"INTEGER","REAL"};
	std::string arith_operators[5]={"+","-","*","/","^"};
	std::string arith_mnemonic[5]={"SUM","SUB","MUL","DIV","POW"};
	for (int i=0;i<5;i++)
	{
		for (int j=0;j<2;j++)
		{
			Method m;
			m.m_classname="REAL";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("REAL"));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=arith_mnemonic[i]+possible_args[j];
			m.m_realname=methodname;
			real->addMethod(methodname,m);
			real->addOperator(Operator(m.m_clients,m.m_classname,methodname,arith_operators[i]));
		}
	}
    
    }

	//Compare operators
	{
	 std::string possible_args[2]={"INTEGER","REAL"};
	 std::string arith_operators[8]={"<",">","<=",">=","~","/~","=","/="};
	 std::string arith_mnemonic[8]={"LS","GT","LEQ","GEQ","SEQ","NSEQ","EQ","NEQ"};

	 for (int i=0;i<8;i++)
	 {
		for (int j=0;j<2;j++)
		{
			Method m;
			m.m_classname="REAL";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("BOOLEAN"));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=arith_mnemonic[i]+possible_args[j];
			m.m_realname=methodname;
			real->addMethod(methodname,m);
			real->addOperator(Operator(m.m_clients,m.m_classname,methodname,arith_operators[i]));
		}
	 }
	
	}

	std::string possible_types[3]={"INTEGER","CHARACTER","STRING"};
	//Converts to
	{
	 std::string to="TO_";
     for (int i=0;i<3;i++)
	 {
			Method m;
			m.m_classname="REAL";
			m.m_clients.push_back("ANY");
			//m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string(possible_types[i]));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;
		
			std::string methodname=to+possible_types[i];
			m.m_realname=methodname;
			real->addMethod(methodname,m);
			real->addConvertTo(possible_types[i],methodname);
	 }
	}
	//Converts from
	{
	 std::string from="FROM_";
     for (int i=0;i<3;i++)
	 {
			Method m;
			m.m_classname="REAL";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_types[i]))));
			m.m_return_type=NULL;
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=from+possible_types[i];
			m.m_realname=methodname;
			real->addMethod(methodname,m);
			real->addConvertFrom(possible_types[i],methodname);
	 }
	}

	addLibraryClass("REAL",real);
}



void SemanticVisitorData::createCharacter()
{
	ClassSemantic * character=new ClassSemantic();
	character->toggleVisited();
	character->m_is_interface=false;
	character->addInheritance("ANY",InheritanceSemantic());
	character->m_class=new ClassNode(YYLTYPE(),new std::string("CHARACTER"));
	
	Method clone;
	clone.m_classname="CHARACTER";
	clone.m_clients.push_back("ANY");
	clone.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("CHARACTER"));
	clone.m_routine=NULL;
	clone.m_type=FDT_LIBRARY;
	clone.m_realname="CLONE";
	character->addMethod("CLONE",clone);
	
	//Arithmetic
	{
	
	std::string possible_args[2]={"CHARACTER","INTEGER"};
	std::string arith_operators[5]={"+","-","*","/"};
	std::string arith_mnemonic[5]={"SUM","SUB","MUL","DIV"};
	for (int i=0;i<4;i++)
	{
		for (int j=0;j<2;j++)
		{
			Method m;
			m.m_classname="CHARACTER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("CHARACTER"));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=arith_mnemonic[i]+possible_args[j];
			m.m_realname=methodname;
			character->addMethod(methodname,m);
			character->addOperator(Operator(m.m_clients,m.m_classname,methodname,arith_operators[i]));
		}
	}
    
    }

	//Compare operators
	{
	 std::string possible_args[1]={"CHARACTER"};
	 std::string arith_operators[8]={"<",">","<=",">=","~","/~","=","/="};
	 std::string arith_mnemonic[8]={"LS","GT","LEQ","GEQ","SEQ","NSEQ","EQ","NEQ"};

	 for (int i=0;i<8;i++)
	 {
		for (int j=0;j<1;j++)
		{
			Method m;
			m.m_classname="CHARACTER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("BOOLEAN"));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=arith_mnemonic[i]+possible_args[j];
			m.m_realname=methodname;
			character->addMethod(methodname,m);
			character->addOperator(Operator(m.m_clients,m.m_classname,methodname,arith_operators[i]));
		}
	 }
	
	}

	std::string possible_types[3]={"INTEGER","REAL","STRING"};
	//Converts to
	{
	 std::string to="TO_";
     for (int i=0;i<3;i++)
	 {
			Method m;
			m.m_classname="CHARACTER";
			m.m_clients.push_back("ANY");
			//m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_args[j]))));
			m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string(possible_types[i]));
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=to+possible_types[i];
			m.m_realname=methodname;
			character->addMethod(methodname,m);
			character->addConvertTo(possible_types[i],methodname);
	 }
	}
	//Converts from
	{
	 std::string from="FROM_";
     for (int i=0;i<3;i++)
	 {
			Method m;
			m.m_classname="CHARACTER";
			m.m_clients.push_back("ANY");
			m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(possible_types[i]))));
			m.m_return_type=NULL;
			m.m_routine=NULL;
			m.m_type=FDT_LIBRARY;

			std::string methodname=from+possible_types[i];
			m.m_realname=methodname;
			character->addMethod(methodname,m);
			character->addConvertFrom(possible_types[i],methodname);
	 }
	}

	addLibraryClass("CHARACTER",character);
}


void SemanticVisitorData::createString()
{
  ClassSemantic *string=new ClassSemantic();
  string->toggleVisited();
  string->m_is_interface=false;
  string->addInheritance("ANY",InheritanceSemantic());
  string->m_class=new ClassNode(YYLTYPE(),new std::string("STRING"));
  
  Method clone;
  clone.m_classname="STRING";
  clone.m_clients.push_back("ANY");
  clone.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("STRING"));
  clone.m_routine=NULL;
  clone.m_type=FDT_LIBRARY;
  clone.m_realname="CLONE";
  string->addMethod("CLONE",clone);
  
  //Get character
  {
	Method m;
	m.m_classname="STRING";
	m.m_clients.push_back("ANY");
	m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"))));
	m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("CHARACTER"));
	m.m_routine=NULL;
	m.m_type=FDT_LIBRARY;

	std::string methodname="GET_CHAR";
	m.m_realname=methodname;
	string->addMethod(methodname,m);
	string->addOperator(Operator(m.m_clients,m.m_classname,methodname," []"));
  }
  //Put character
  {
	Method m;
	m.m_classname="STRING";
	m.m_clients.push_back("ANY");
	m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"))));
	m.m_formal_args.push_back(ArgEntry("y",new ClassTypeNode(YYLTYPE(),new std::string("CHARACTER"))));
	m.m_return_type=NULL;
	m.m_routine=NULL;
	m.m_type=FDT_LIBRARY;

	std::string methodname="PUT_CHAR";
	m.m_realname=methodname;
	string->addMethod(methodname,m);
	string->addOperator(Operator(m.m_clients,m.m_classname,methodname," []="));
  }
  //Returns length of string
  {
	Method m;
	m.m_classname="STRING";
	m.m_clients.push_back("ANY");
	m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"));
	m.m_routine=NULL;
    m.m_type=FDT_LIBRARY;
	std::string methodname="LENGTH";
	m.m_realname=methodname;
	string->addMethod(methodname,m);
  }
  addLibraryClass("STRING",string);
}


void SemanticVisitorData::createBoolean()
{
  ClassSemantic * boolean=new ClassSemantic();
  boolean->toggleVisited();
  boolean->m_is_interface=false;
  boolean->addInheritance("ANY",InheritanceSemantic());
  boolean->m_class=new ClassNode(YYLTYPE(),new std::string("BOOLEAN"));

  Method clone;
  clone.m_classname="BOOLEAN";
  clone.m_clients.push_back("ANY");
  clone.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("BOOLEAN"));
  clone.m_routine=NULL;
  clone.m_type=FDT_LIBRARY;
  boolean->addMethod("BOOLEAN",clone);
  //Not operator
  {
	Method m;
	m.m_classname="BOOLEAN";
	m.m_clients.push_back("ANY");
	m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("BOOLEAN"));
	m.m_routine=NULL;
    m.m_type=FDT_LIBRARY;

	std::string methodname="MNOT";
	m.m_realname=methodname;
	boolean->addMethod(methodname,m);
	boolean->addOperator(Operator(m.m_clients,m.m_classname,methodname,"not"));
  }
  //And other operators
  std::string ops[6]={"implies","and then","or else","or","xor","and"};
  std::string mops[6]={"MIMPLIES","MANDTHEN","MORELSE","MOR","MXOR","MAND"};

  for (int i=0;i<6;i++)
  {
	Method m;
	m.m_classname="BOOLEAN";
	m.m_clients.push_back("ANY");
	m.m_formal_args.push_back(ArgEntry("y",new ClassTypeNode(YYLTYPE(),new std::string("BOOLEAN"))));
	m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("BOOLEAN"));
	m.m_routine=NULL;
    m.m_type=FDT_LIBRARY;
	m.m_realname=mops[i];
	boolean->addMethod(mops[i],m);
	boolean->addOperator(Operator(m.m_clients,m.m_classname,mops[i],ops[i]));
  }
  addLibraryClass("BOOLEAN",boolean);
}


void SemanticVisitorData::createArrayType(const std::string & compatibleType)
{
	std::string type="ARRAY[";
	type+=compatibleType;
	type+="]";

	if (m_libraryclasses.find(type)!=m_libraryclasses.end())
		return;


  ClassSemantic * arr=new ClassSemantic();
  arr->toggleVisited();
  arr->addInheritance("ANY",InheritanceSemantic());
  arr->m_class=new ClassNode(YYLTYPE(),new std::string("ARRAY"));
  arr->m_is_interface=false;

  Method init;
  init.m_classname="ARRAY";
  init.m_clients.push_back("ANY");
  init.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"))));
  init.m_return_type=NULL;
  init.m_routine=NULL;
  init.m_type=FDT_LIBRARY | FDT_FROZEN;
  init.m_realname="MAKE";
  init.predefineSignature("ARRAY","ARRAYMAKE","(LINTEGER;)V");
  arr->addMethod("MAKE",init);
  arr->addConstructor("MAKE",init.m_clients);

  //Get object
  {
	Method m;
	m.m_classname="ARRAY";
	m.m_clients.push_back("ANY");
	m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"))));
	m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string(compatibleType));
	m.m_routine=NULL;
	m.m_type=FDT_LIBRARY;
	m.m_realname="GET";
	m.predefineSignature("ARRAY","ARRAYGET","(LINTEGER;)Ljava/lang/Object;");
	std::string methodname="GET";
	arr->addMethod(methodname,m);
	arr->addOperator(Operator(m.m_clients,m.m_classname,methodname,"[]"));
  }
  //Put object
  {
	Method m;
	m.m_classname="ARRAY";
	m.m_clients.push_back("ANY");
	m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"))));
	m.m_formal_args.push_back(ArgEntry("y",new ClassTypeNode(YYLTYPE(),new std::string(compatibleType))));
	m.m_return_type=NULL;
	m.m_routine=NULL;
	m.m_type=FDT_LIBRARY;
	m.m_realname="PUT";
	m.predefineSignature("ARRAY","ARRAYPUT","(LINTEGER;Ljava/lang/Object;)V");

	std::string methodname="PUT";
	arr->addMethod(methodname,m);
	arr->addOperator(Operator(m.m_clients,m.m_classname,methodname,"[]:="));
  }
  //Returns length of string
  {
	Method m;
	m.m_classname="ARRAY";
	m.m_clients.push_back("ANY");
	m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string("INTEGER"));
	m.m_routine=NULL;
    m.m_type=FDT_LIBRARY;
	m.m_realname="COUNT";
	m.predefineSignature("ARRAY","ARRAYLENGTH","()LINTEGER;");

	std::string methodname="COUNT";
	arr->addMethod(methodname,m);
  }
   addLibraryClass(type,arr);
}

void SemanticVisitorData::createStreams()
{
 {
  std::string type="STD_INPUT_STREAM";
  ClassSemantic * arr=new ClassSemantic();
  arr->toggleVisited();
  arr->m_is_interface=false;
  arr->addInheritance("ANY",InheritanceSemantic());
  arr->m_class=new ClassNode(YYLTYPE(),new std::string(type));
 
  Method init;
  init.m_classname=type;
  init.m_clients.push_back("ANY");
  init.m_return_type=NULL;
  init.m_routine=NULL;
  init.m_type=FDT_LIBRARY | FDT_FROZEN;
  init.m_realname="INIT";
  arr->addMethod("INIT",init);
  arr->addConstructor("INIT",init.m_clients);

  std::string getTypes[4]={"INTEGER","REAL","CHARACTER","STRING"};
  for (int i=0;i<4;i++)
  {
	Method m;
	m.m_classname=type;
	m.m_clients.push_back("ANY");
	m.m_return_type=new ClassTypeNode(YYLTYPE(),new std::string(getTypes[i]));
	m.m_routine=NULL;
    m.m_type=FDT_LIBRARY;
	m.m_realname=std::string("GET_")+getTypes[i];
	arr->addMethod(m.m_realname,m);
  }

  addLibraryClass(type,arr);
 }
 {
  std::string type="STD_OUTPUT_STREAM";
  ClassSemantic * arr=new ClassSemantic();
  arr->toggleVisited();
  arr->m_is_interface=false;
  arr->addInheritance("ANY",InheritanceSemantic());
  arr->m_class=new ClassNode(YYLTYPE(),new std::string(type));
 
  Method init;
  init.m_classname=type;
  init.m_clients.push_back("ANY");
  init.m_return_type=NULL;
  init.m_routine=NULL;
  init.m_type=FDT_LIBRARY | FDT_FROZEN;
  init.m_realname="INIT";
  arr->addMethod("INIT",init);
  arr->addConstructor("INIT",init.m_clients);

  std::string getTypes[4]={"INTEGER","REAL","CHARACTER","STRING"};
  for (int i=0;i<4;i++)
  {
	Method m;
	m.m_classname=type;
	m.m_clients.push_back("ANY");
	m.m_formal_args.push_back(ArgEntry("x",new ClassTypeNode(YYLTYPE(),new std::string(getTypes[i]))));
	m.m_return_type=NULL;
	m.m_routine=NULL;
    m.m_type=FDT_LIBRARY;
	m.m_realname=std::string("PUT_")+getTypes[i];
	arr->addMethod(m.m_realname,m);
  }

  addLibraryClass(type,arr);
 }
 
}